package me.liquidifica.agil.service.util;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;

import me.liquidifica.agil.service.general.impl.CopyOfHelloWorldManager;
import me.liquidifica.agil.service.general.impl.Copy_2_of_HelloWorldManager;
import me.liquidifica.agil.service.general.impl.HelloWorldManager;

import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.WebResource;

public class ServiceGenerator {

	public static void main(String[] args) throws IOException {

		String address = "localhost:8080/agil-service";
		
		if(args.length > 0){
			address = args[0];
		}

		Map<String, List<Class<?>>> services = new HashMap<String, List<Class<?>>>();
		
		getServices(services);

		for (Entry<String, List<Class<?>>> entry : services.entrySet()) {
			
			final File file = new File("../agil-web/src/main/java/me/liquidifica/agil/web/generated/" + entry.getKey() + "Service.java");
			
			if(file.exists()){
				file.delete();
			}
			
			file.createNewFile();
			
			final FileWriter writer = new FileWriter(file);
			
			writer.write("package me.liquidifica.agil.web.generated;");
			writer.write("\n");
			writer.write("\npublic class " + entry.getKey() + "Service { ");
			writer.write("\n");
			writer.write("\n    public final static String ADDRESS = \"" + address +"\";");
			writer.write("\n");
			
			for(Class<?> clazz : entry.getValue()){
				
				writer.write("\n");
				writer.write("\n    /*" + clazz.getSimpleName() + "*/");
				writer.write("\n");

				for(Method method : clazz.getMethods()){
					
					try {
						Object.class.getMethod(method.getName(), method.getParameterTypes());
						continue;
					} catch (NoSuchMethodException e) {
					} catch (SecurityException e) {
					}
						
					writer.write("\n    public " + method.getReturnType().getCanonicalName() + " " + method.getName() + " (");

					int i = 0;
					for(Class<?> param : method.getParameterTypes()){

						if(i > 0){
							writer.write(", ");
						}
						
						writer.write(param.getCanonicalName() + " " + ((PathParam)method.getParameterAnnotations()[i++][0]).value());
						
					}
					
					writer.write(") {");
					writer.write("\n        " + Client.class.getCanonicalName() + " client = " + Client.class.getCanonicalName() + ".create(); ");
					writer.write("\n        " + WebResource.class.getCanonicalName() + " webResource = client.resource(\"http://\" + ADDRESS + \"" + clazz.getAnnotation(Path.class).value() + "\"");
					
					int j = 0;
					for(Class<?> param : method.getParameterTypes()){
						writer.write("+ \"/\" + " + ((PathParam)method.getParameterAnnotations()[j++][0]).value());
					}
					
					writer.write(");");
					
					writer.write("\n        " + ClientResponse.class.getCanonicalName() + " response = webResource.accept(\"" + method.getAnnotation(Produces.class).value()[0] + "\").get(" + ClientResponse.class.getCanonicalName() + ".class); ");
					writer.write("\n        if (response.getStatus() != 200) { ");
					writer.write("\n           throw new RuntimeException(\"Failed : HTTP error code : \" + response.getStatus());");
					writer.write("\n        } ");
					writer.write("\n        return response.getEntity(" + method.getReturnType().getCanonicalName() + ".class);");
					writer.write("\n    }");
					writer.write("\n");

				}
				
			}
			
			writer.write("\n}");
			
			writer.flush();
			writer.close();
			
		}
		
		
	}

	private static void getServices(Map<String, List<Class<?>>> services) {
		services.put("General", new ArrayList<Class<?>>());
		services.get("General").add(HelloWorldManager.class);
		services.get("General").add(CopyOfHelloWorldManager.class);
		services.get("General").add(Copy_2_of_HelloWorldManager.class);
	}
	
}
